<template>
  <header class="title">软考计算公式列表</header>

  <div class="talk-box">
    <header>计算沟通渠道数：</header>
    <div class="content">
      沟通渠道(n * (n-1))/2；<el-input v-model="computedTalkType" @input="computeSumFunc" />
      <span
        >总渠道数为: <span style="color: red">{{ talkSum }}</span></span
      >
    </div>
  </div>
  <div class="talk-box">
    <header>三点估算：</header>
    <div class="content">
      <div class="item">
        最悲观时间: <el-input type="text" placeholder="最悲观时间" v-model="worstTime" @input="computedSd(1)" />
      </div>
      <div class="item">
        最乐观时间: <el-input type="text" placeholder="最乐观时间" v-model="bestTime" @input="computedSd(2)" />
      </div>
      <div class="item">
        最可能时间: <el-input type="text" placeholder="最可能时间" v-model="mebeTime" @input="computedSd(3)" />
      </div>
    </div>
    <div class="content">
      标准差（最悲观 - 最乐观）/ 6: <span style="color: red">{{ basicEachNum }}</span>
    </div>
    <div class="content">
      期望值（最悲观 + 最乐观 + 4 * 最可能）/ 6: <span style="color: red">{{ desiredValue }}</span>
    </div>
  </div>
  <div class="talk-box">
    <header>挣值管理:</header>
    <div class="content">
      <div class="item">BAC(总预算)；<el-input v-model="earnedForm.bac" @input="computedEarned" /></div>
      <div class="item">
        偏差类型：
        <el-select v-model="earnedForm.deviationType" @change="computedEarned">
          <el-option :value="1" label="典型偏差" />
          <el-option :value="2" label="非典型偏差" />
        </el-select>
      </div>
    </div>
    <div class="content">
      <div class="item">PV(计划成本)；<el-input v-model="earnedForm.planValue" @input="computedEarned" /></div>
      <div class="item">AC(实际成本)；<el-input v-model="earnedForm.actualValue" @input="computedEarned" /></div>
      <div class="item">EV(挣值)；<el-input v-model="earnedForm.earnedValue" @input="computedEarned" /></div>
    </div>
    <div class="content">
      SV(进度偏差 = EV-PV):
      <span style="color: red">{{ earnedForm.sv }} （{{ earnedForm.sv > 0 ? '进度超前' : '进度滞后' }}）</span>
    </div>
    <div class="content">
      CV(成本偏差 = EV-AC):
      <span style="color: red">{{ earnedForm.cv }} （{{ earnedForm.cv > 0 ? '成本节约' : '成本超支' }}）</span>
    </div>
    <div class="content">
      SPI(进度绩效指数 = EV / PV):
      <span style="color: red"
        >{{ earnedForm.spi * 100 + '%' }} （{{ earnedForm.spi > 1 ? '进度超前' : '进度滞后' }}）</span
      >
    </div>
    <div class="content">
      CPI(成本绩效指数 = EV / CV):
      <span style="color: red"
        >{{ earnedForm.cpi * 100 + '%' }} （{{ earnedForm.cpi > 1 ? '成本节约' : '成本超支' }}）</span
      >
    </div>
    <div class="content" v-show="earnedForm.deviationType === 1">
      ETC(典型偏差 = BAC - EV / CPI): <span style="color: red">{{ earnedForm.etc }}</span>
    </div>
    <div class="content" v-show="earnedForm.deviationType === 2">
      ETC(非典型偏差 = BAC - EV): <span style="color: red">{{ earnedForm.etc }}</span>
    </div>
    <div class="content">
      EAC(完工预算 = ETC + AC): <span style="color: red">{{ earnedForm.eac }}</span>
    </div>
  </div>
</template>

<script lang="ts" setup>
  import { reactive, ref, getCurrentInstance } from 'vue'
  const { proxy } = getCurrentInstance()
  const computedTalkType = ref(0) //沟通渠道数
  var talkSum = ref(0)
  const rep = /^\d+(\d)?$/
  const computeSumFunc = () => {
    if (computedTalkType.value && rep.test(computedTalkType.value + '')) {
      talkSum.value = (computedTalkType.value * (computedTalkType.value - 1)) / 2
    } else {
      ;(proxy as any).$message.error('请输入正整数')
    }
  }
  const basicEachNum = ref(0) //三点估算
  const desiredValue = ref(0)
  const worstTime = ref(0)
  const bestTime = ref(0)
  const mebeTime = ref(0)
  const computedSd = (num: Number) => {
    if (num === 1) {
      //来自于悲观时间
      if (worstTime.value && rep.test(worstTime.value + '')) {
        if (bestTime.value && rep.test(bestTime.value + '') && worstTime.value >= bestTime.value) {
          basicEachNum.value = Number(((worstTime.value * 100 - bestTime.value * 100) / 100 / 6).toFixed(2))
          if (mebeTime.value && rep.test(mebeTime.value + '')) {
            desiredValue.value = Number(
              ((worstTime.value * 100 + bestTime.value * 100 + 4 * mebeTime.value * 100) / 100 / 6).toFixed(2)
            )
          }
        } else {
          ;(proxy as any).$message.error('最悲观时间应大于最乐观时间')
        }
      } else {
        ;(proxy as any).$message.error('请输入正整数')
      }
    } else if (num === 2) {
      //来自乐观时间
      if (bestTime.value && rep.test(bestTime.value + '')) {
        if (worstTime.value && rep.test(worstTime.value + '') && worstTime.value >= bestTime.value) {
          basicEachNum.value = Number(((worstTime.value * 100 - bestTime.value * 100) / 100 / 6).toFixed(2))
          if (mebeTime.value && rep.test(mebeTime.value + '')) {
            desiredValue.value = Number(
              ((worstTime.value * 100 + bestTime.value * 100 + 4 * mebeTime.value * 100) / 100 / 6).toFixed(2)
            )
          }
        } else {
          ;(proxy as any).$message.error('最悲观时间应大于最乐观时间')
        }
      } else {
        ;(proxy as any).$message.error('请输入正整数')
      }
    } else if (num === 3) {
      if (mebeTime.value && rep.test(mebeTime.value + '')) {
        if (
          bestTime.value &&
          worstTime.value &&
          rep.test(bestTime.value + '') &&
          rep.test(worstTime.value + '') &&
          worstTime.value >= bestTime.value
        ) {
          desiredValue.value = Number(
            ((worstTime.value * 100 + bestTime.value * 100 + 4 * mebeTime.value * 100) / 100 / 6).toFixed(2)
          )
        } else {
          ;(proxy as any).$message.error('最悲观时间应大于最乐观时间')
        }
      } else {
        ;(proxy as any).$message.error('请输入正整数')
      }
    }
  }

  const earnedForm = reactive({
    deviationType: 1,
    planValue: 0,
    earnedValue: 0,
    actualValue: 0,
    sv: 0,
    cv: 0,
    spi: 0,
    cpi: 0,
    bac: 0,
    etc: 0,
    eac: 0 //完工估算
  })
  //当偏差类型发生改变
  const computedEarned = () => {
    if (earnedForm.planValue && rep.test(earnedForm.planValue + '')) {
      //pv 有值 情况 去看  ev 有没有值，如果有值就可以算出sv 和spi
      if (earnedForm.earnedValue && rep.test(earnedForm.earnedValue + '')) {
        earnedForm.sv = (earnedForm.earnedValue * 100 - earnedForm.planValue * 100) / 100
        earnedForm.spi = Number((earnedForm.earnedValue / earnedForm.planValue).toFixed(2))
      }
    }
    if (earnedForm.actualValue && rep.test(earnedForm.actualValue + '')) {
      //ac 有值，可以去看ev 有无值 ，算出cv和cpi
      if (earnedForm.earnedValue && rep.test(earnedForm.earnedValue + '')) {
        earnedForm.cv = (earnedForm.earnedValue * 100 - earnedForm.actualValue * 100) / 100
        earnedForm.cpi = Number((earnedForm.earnedValue / earnedForm.actualValue).toFixed(2))
        if (earnedForm.bac && rep.test(earnedForm.bac + '')) {
          //bac存在 则可以算出对应的etc 和eac
          if (earnedForm.deviationType === 1) {
            //典型偏差 etc
            earnedForm.etc = Number(((earnedForm.bac - earnedForm.earnedValue) / earnedForm.cpi).toFixed(2))
            earnedForm.eac = Number(((earnedForm.etc * 100 + earnedForm.actualValue * 100) / 100).toFixed(2))
          } else {
            //非典型偏差 etc
            earnedForm.etc = Number((earnedForm.bac - earnedForm.earnedValue).toFixed(2))
            earnedForm.eac = Number(((earnedForm.etc * 100 + earnedForm.actualValue * 100) / 100).toFixed(2))
          }
        }
      }
    }
  }
</script>

<style lang="scss" scoped>
  .title {
    font-size: 20px;
    font-weight: bold;
  }
  .talk-box {
    margin: 20px;
    & > header {
      margin: 10px 0;
      font-size: 18px;
      font-weight: bold;
    }
    & > .content {
      clear: both;
      margin: 5px 20px;
      > .el-input {
        width: 200px;
      }
      .item {
        float: left;
        margin: 0 30px 8px 0;
        > .el-input {
          width: 150px;
        }
      }
      > span {
        margin: 0 20px;
      }
    }
  }
</style>
